package com.flycms.module.agent;

import com.alibaba.druid.util.StringUtils;
import com.flycms.config.DruidDataSourceConfigurer;
import com.flycms.core.utils.DateUtils;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @author huangzt
 * @version 1.0
 * @date 2020/3/1 14:31
 */
@Component
@Getter
@Setter
public class UserAgentUtils {
    private final static Logger logger = LoggerFactory.getLogger(UserAgentUtils.class);

    @Autowired
    DruidDataSourceConfigurer dataSourceConfigurer;

    static DataSource datasource;
    public static JdbcTemplate jdbcTemplate;
    static List<VisitPersonVo> visitors = new ArrayList<>();
    /**
     * 访客属性
     */
    public static ConcurrentHashMap<String, Date> visitorMap = new ConcurrentHashMap<>();
    /**
     * 统计属性（访客量，访问量，ip总量，新增访客）
     */
    public static ConcurrentHashMap<String, Long> visitViewMap = new ConcurrentHashMap<>();

    public static AtomicLong solutionCount = new AtomicLong(0);

    /**
     * 将注入的bean初始化为静态变量
     */
    @PostConstruct
    void init() {
        datasource = dataSourceConfigurer.getDataSource();
        jdbcTemplate = new JdbcTemplate(datasource);
        String sql = "select * from fly_visit_person";
        visitors = jdbcTemplate.query(sql, new VisitPersonRowMapper());
        visitorMap = visitors.stream().collect(Collectors.toMap(
                a -> a.getAgent() + "##" + a.getIp(), VisitPersonVo::getTime,
                (oldVal, currVal) -> currVal, ConcurrentHashMap::new));
        String sql2 = "select * from fly_visit";
        visitViewMap = jdbcTemplate.queryForObject(sql2, new VisitRowMapper());
        solutionCount.set(visitViewMap.get("solution_visitor"));
    }

    public static void conTest(HttpServletRequest request){
        String requestURL = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getServletPath();
        if (requestURL.endsWith(".css") || requestURL.endsWith(".js") ||
                requestURL.endsWith(".png") || requestURL.endsWith(".woff2") ||
                requestURL.endsWith(".ico") || requestURL.endsWith(".woff") ||
                requestURL.endsWith(".gif") || requestURL.endsWith(".css") ||
                requestURL.endsWith(".jpg") || requestURL.endsWith("nullPermission")) {
            return;
        }
        //获取浏览器信息
        Browser browser = UserAgent.parseUserAgentString(request.getHeader("User-Agent")).getBrowser();
        String ip = getRemoteIp(request);
        //获取浏览器版本号
        String info;
        Version version = browser.getVersion(request.getHeader("User-Agent"));
        if (version == null) {
            info = "PostmanRuntime/7.22.0";
        } else {
            info = browser.getName() + "/" + version.getVersion();
        }
        String key = info + "##" + ip;
        /**
         * 统计方法
         */
        setVisitor(key);
        setVisit();
    }

    /**
     * 统计访客量
     * @param key
     */
    public static void setVisitor(String key){
        Date newDate = new Date();
        if (visitorMap.containsKey(key)) {
            //存在key是改变值
            Date date = visitorMap.get(key);
            long daySub = DateUtils.getDaySub(DateUtils.fomatDateToString(date), DateUtils.fomatDateToString(newDate));
            if (daySub > 1) {
                // 更新进缓存
                Long unique_visitor = visitViewMap.get("unique_visitor");
                visitViewMap.put("unique_visitor", unique_visitor + 1);
                //更新录入时间
                visitorMap.put(key, newDate);
                logger.info("更新成功，当前访客总数：" + visitViewMap.get("unique_visitor"));
                Long new_unique_visitor = visitViewMap.get("new_unique_visitor");
                visitViewMap.put("new_unique_visitor", new_unique_visitor + 1);
                logger.info("更新成功，当前今日访客总数：" + visitViewMap.get("new_unique_visitor"));
            }
        } else {
            //不存在key新增值
            visitorMap.put(key, newDate);
            Long unique_visitor = visitViewMap.get("unique_visitor");
            visitViewMap.put("unique_visitor", unique_visitor + 1);
            logger.info("更新成功，当前访客总数：" + visitViewMap.get("unique_visitor"));
            Long new_unique_visitor = visitViewMap.get("new_unique_visitor");
            visitViewMap.put("new_unique_visitor", new_unique_visitor + 1);
            logger.info("更新成功，当前今日新访客总数：" + visitViewMap.get("new_unique_visitor"));
        }
    }

    /**
     * 统计访问总量
     */
    public static void setVisit() {
        /**
         * 更新全站网页访问总数
         */
        Long pageView = visitViewMap.get("page_view");
        visitViewMap.put("page_view", pageView + 1);
        logger.info("更新成功，当前访问总数：" + visitViewMap.get("page_view"));
    }

    /**
     * 获取IP地址
     *
     * @param request HttpServletRequest
     * @return IP地址
     */
    public static String getRemoteIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        return ip;
    }

}



